package org.arch_learn.rpc.nz_rpc.utils;

import org.arch_learn.rpc.nz_rpc.annos.RpcReference;
import org.arch_learn.rpc.nz_rpc.annos.RpcService;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;

public class ScanUtils {
    //加载rpc服务提供类
    public static void loadServices(String rootPackage, Set<String> services) throws IOException, ClassNotFoundException {
        String scanPackagePath = Thread.currentThread().getContextClassLoader()
                .getResource("").getPath() + rootPackage.replaceAll("\\.", "/");

        File file = new File(scanPackagePath);
        File[] files = file.listFiles();
        for (File f : files) {
            if (f.isDirectory()) {
                loadServices(rootPackage + "." + f.getName(), services);
            } else if (f.getName().endsWith(".class")) {
                String name = f.getName().replaceAll("\\.class", "");
                String className = rootPackage + "." + name;
                Class<?> aClass = Class.forName(className);

                if (aClass.isAnnotationPresent(RpcService.class)) {
                    services.add(aClass.getInterfaces()[0].getName());
                }
            }
        }
    }

    //加载rpc服务引用
    public static void loadReferences(String rootPackage, Set<String> rpcReferences) throws ClassNotFoundException {
        String scanPackagePath = Thread.currentThread().getContextClassLoader()
                .getResource("").getPath() + rootPackage.replaceAll("\\.", "/");

        File file = new File(scanPackagePath);
        File[] files = file.listFiles();
        for (File f : files) {
            if (f.isDirectory()) {
                loadReferences(rootPackage + "." + f.getName(), rpcReferences);
            } else if (f.getName().endsWith(".class")) {
                String name = f.getName().replaceAll("\\.class", "");
                String className = rootPackage + "." + name;
                Class<?> aClass = Class.forName(className);
                Set<String> referenceClasses = Arrays.stream(aClass.getDeclaredFields())
                        .filter(v -> v.isAnnotationPresent(RpcReference.class))
                        .map(filed -> filed.getType().getName())
                        .collect(Collectors.toSet());
                rpcReferences.addAll(referenceClasses);
            }
        }

    }
}
